import { RootStackParamList, RouterKey } from '@NAVIGATION/NavigationType'
import { createNavigationContainerRef, StackActions } from '@react-navigation/native'

export type CustomerFunc = {
  // @ts-ignore
  [key in RouterKey]: undefined extends RootStackParamList[key]
    // @ts-ignore
    ? () => void : (params: RootStackParamList[key]) => void
}

class NavigationCustom {
  private readonly interRef = createNavigationContainerRef<RootStackParamList>()

  constructor() {
    Object.keys(RouterKey).forEach((key) => {
      // @ts-ignore
      this[key as keyof RouterKey] = (params: RootStackParamList[key]) => {
        // @ts-ignore
        this.push(key, params)
      }
    })
  }

  get navigationRef() {
    return this.interRef
  }

  navigate<RouteName extends keyof RootStackParamList>(...args: RouteName extends unknown
    ? undefined extends RootStackParamList[RouteName]
      ?
      | [screen: RouteName]
      | [screen: RouteName, params: RootStackParamList[RouteName]]
      : [screen: RouteName, params: RootStackParamList[RouteName]]
    : never) {
    if (this.interRef.isReady()) {
      this.interRef.navigate(...args)
    }
  }

  push<RouteName extends keyof RootStackParamList>(...args: RouteName extends unknown
    ? undefined extends RootStackParamList[RouteName]
      ?
      | [screen: RouteName]
      | [screen: RouteName, params: RootStackParamList[RouteName]]
      : [screen: RouteName, params: RootStackParamList[RouteName]]
    : never) {
    if (this.interRef.isReady()) {
      this.interRef.dispatch(
        StackActions.push(args[0], args[1]),
      )
    }
  }

  replace<RouteName extends keyof RootStackParamList>(...args: RouteName extends unknown
    ? undefined extends RootStackParamList[RouteName]
      ?
      | [screen: RouteName]
      | [screen: RouteName, params: RootStackParamList[RouteName]]
      : [screen: RouteName, params: RootStackParamList[RouteName]]
    : never) {
    if (this.interRef.isReady()) {
      this.interRef.dispatch(
        StackActions.replace(args[0], args[1]),
      )
    }
  }

  goBack(count = 1) {
    if (this.interRef.isReady()) {
      this.interRef.dispatch(
        StackActions.pop(count),
      )
    }
  }

  popToTop() {
    if (this.interRef.isReady()) {
      this.interRef.dispatch(
        StackActions.popToTop(),
      )
    }
  }

  reset<RouteName extends keyof RootStackParamList>(...args: RouteName extends unknown
      ? undefined extends RootStackParamList[RouteName]
        ?
        | [screen: RouteName]
        | [screen: RouteName, params: RootStackParamList[RouteName]]
        : [screen: RouteName, params: RootStackParamList[RouteName]]
      : never) {
    if (this.interRef.isReady()) {
      this.interRef.reset({
        index: 0,
        routes: [{ name: args[0] as string, params: args[1] }],
      })
    }
  }
}

// @ts-ignore
const Navigation: NavigationCustom & CustomerFunc = new NavigationCustom()

export default Navigation
export { RouterKey }
